#include "Biblioteca.h"
  // maxi
//#include "control.h"
#include <stdio.h>
#include <stdlib.h>
//#define PATH_SP "/home/alumnos/2014_Q2/sc2_so/c04/jdeiros/Entregas/TP4/ServerMatch/ServerMatch"
#define PATH_SP "../ServerMatch/Debug/ServerMatch"
//#define PATH_SP "../ServerMatch/Debug/ServerMatch"
#define PATH_MON "../MonitorTorneo/Debug/MonitorTorneo"
#define length(X) (sizeof(X)/sizeof(X[0]))

// maxi
#define SHMKEY 48


int id_memo
	,indice=0
	,y
	,flag_conexiones
	,cant_partidas=0
	,cant_partidasRearmadas=0
	,finalizado
	,status, status2
	,finTiempoDeconexion
	,monoIzqDer=0
	,posicionY = 440
	,limitePantallaTextoFinTorneoInferior=440
	,limitePantallaTextoFinTorneoSuperior = 200
	,senalHijos = 0;

t_torneo *torneo;
TTF_Font *fuente;
//borrado de semaforos sin usar.
sem_t * semPartidas, *semMemoria;
config_serv config;
pthread_t threadEscucha, threadDibuja, threadTiempo, threadTeclas, threadMonitorearServidor;
pthread_t threadMonitor;

// maxi
pthread_mutex_t mutex_monitor = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_monitor = PTHREAD_COND_INITIALIZER;


TTF_Font *fuente0,*fuente1, *fuente2, *fuente3, *fuenteMB_14, *fuenteMB_16, *fuenteMB_18,*fuenteMB_22,*fuenteMB_40,*fuenteMB_180;
SDL_Color colorfuente, colorfuente2, colorFuenteAmarillo,colorFuenteAzul,colorFuenteBlanco;
SDL_Rect rect,rectMono;
SDL_Surface *screen;
SDL_Surface *ttext;
SDL_Surface *imagen,*imgMono;
SDL_Event event;

string cadena;
key_t clave;
int shmid;
int shmidMonitor;
int shmidMon2;
char *buffer;

int vecPuntos[MAXCLI];
char tablaNombres[MAXCLI][TAMBUF];

bool refrescar;

struct timeval t_inicio, t_actual;

void configurarServer ()
{
	config.cargarConfiguracion();
}

void crearSemaforos()
{
	sem_unlink("/semMemoria");
	sem_unlink("/semPartidas");
	semPartidas = sem_open("/semPartidas", O_CREAT,0644,1);
	semMemoria = sem_open("/semMemoria",O_CREAT,0644,1);
}

void crearThreads()
{
       // Permite que el thread main no lo espere en su ejecucion
     //   pthread_attr_t atributos;
     //   pthread_attr_setdetachstate (&atributos, PTHREAD_CREATE_DETACHED);

	pthread_create(&threadEscucha,NULL,escucharConexiones,NULL);
	pthread_create(&threadDibuja,NULL,dibujarPantalla,NULL);
	pthread_create(&threadTiempo,NULL,controlarTiempo,NULL);
	pthread_create(&threadTeclas,NULL,monitorTeclas,NULL);

        // maxi
	pthread_create(&threadMonitor,NULL,monitorizarMonitor,NULL);
}

void esperarThreadEscucha()
{
	pthread_join(threadEscucha, NULL);
	sleep(1);
}

void esperarThreadDibuja()
{
	pthread_join(threadDibuja, NULL);
}

//Creamos la memoria compartidapost(semM
void crearMemoriaCompartida(key_t clave){

	//genero memoria compartida.
	id_memo = shmget(clave,sizeof(t_torneo),IPC_CREAT | 0666);
	//printf ("id_memo Torneo %d\n", id_memo);
	if(id_memo < 0){
		fprintf(stderr , "Error al crear la memoria compartida.\n");
		exit(0);
	}
	torneo = (t_torneo *) shmat(id_memo,NULL,0);
}

//Cierro sockets de comunicacion, semaforos, etc.
void liberarRecursos()
{
	/*char message[TAMBUF]="torneo";
	int i;
	SDL_FreeSurface(screen);
	cout << "Cerrando Servidor de Torneo" << endl;
	//cout << "Informando a los clientes" << endl;
	//envío a todos los clientes el mensaje
	sem_wait(semMemoria);
	for (i=0;i<torneo->cantJugadores;i++)
	{
		if(torneo->jugador[i].conectado !=0){
			//send(torneo->jugador[i].socket , message , strlen(message) , 0);
			close(torneo->jugador[i].socket);
		}
	}
	sem_post(semMemoria);

	//envío señal a los servidores de partida
	for (i=0;i<cant_partidas;i++)
	{
		sem_wait(semMemoria);
		if(torneo->partidas[i].pid > 0 && torneo->partidas[i].pid!=getpid() && torneo->partidas[i].terminoPartida == 0)
		{
			printf("Enviando señal a Servidor de Partida %d\n", i);
			kill(torneo->partidas[i].pid, SIGUSR1);
		}
		sem_post(semMemoria);
	}

	cout << "Liberando semáforos y memoria compartida" << endl;

	shmdt((t_torneo *)torneo);
	shmctl(id_memo,IPC_RMID, NULL);
	sem_close(semMemoria);
	sem_close(semPartidas);
	sem_unlink("/semMemoria");
	sem_unlink("/semPartidas");
	//free(torneo->partidas); //libero memoria creada para el array de partidas (actualmente tiene max de 50 partidas)
	printf("Saliendo del Torneo...\n");

	exit(1);*/
}

void * monitorearServidor(void *arg){
	// Creo memoria compartida entre los procesos.
	clave = ftok("/bin/ls",'M');
	shmid = shmget(clave, 4096, IPC_CREAT | 0660);
	buffer = (char *)shmat(shmid,NULL,0);
	strcpy(buffer,"VIVO");

	pid_t childPid = fork() ;
	if(childPid == 0) {
		char programName[] = "SimuladorMonitor";
		char *program[] = { programName, (char*) NULL };
		if(execvp(PATH_MON, program)==-1);
			printf ("Error al ejecutar el proceso MONITOR.\n");
	}
	else{
		//wait(NULL);
		while(true){
			sleep(4);
			strcpy(buffer,"VIVO");
		}
	}
	return 0;
}

void inicializarDatos(){

	flag_conexiones=1;
	sem_wait(semMemoria);
	//Inicializa cantidad de jugadores
	torneo->cantJugadores = 0;
	//Inicializo el tiemenvioNombreJugadoresAClientepo en 0;
	torneo->t_chequeo = 0;
	torneo->partidaCaida = 0;
	// Inicializa la variable que controla el fin de las conexiones
	//torneo->flagFinConexiones=0;	// Inicializa puntajes
	// Inicializa cantidad de partidas
	torneo->cantPartidas=0;
	//cargo el archivo de configuracion del servidor
	torneo->tiempo_espera_conex_max = config.getTiempoEsperaConexMax();
	torneo->nivel_dificultad = config.getNivelDificultad();
	torneo->cantidad_rescates = config.getCantidadRescates();
	torneo->tiempo_torneo = config.getTiempoTorneo();
	sem_post(semMemoria);
}

void inicializarSDL(){

	if(SDL_Init(SDL_INIT_VIDEO) < 0){
		printf("No se ha podido inicializar SDL: %s\n",SDL_GetError());
		pthread_exit((void *)1);
	}

	screen= SDL_SetVideoMode(640,480,24,SDL_HWSURFACE | SDL_DOUBLEBUF);
	if(screen == NULL){
		fprintf(stderr,"No se puede establecer el modo de video 640x480: %s\n",SDL_GetError());
		pthread_exit((void *)1);
	}

	SDL_WM_SetCaption("D-Don King Tournament", "D-Don King Tournament");

	if(TTF_Init() < 0){
		printf("No se pudo iniciar SDL_ttf: %s\n",SDL_GetError());
		pthread_exit((void*)1);
	}
	//Cargo las fuentes
	fuente0=TTF_OpenFont("./Fuentes/DBJ.ttf",TAM0);
	fuente1=TTF_OpenFont("./Fuentes/DBJ.ttf",TAM1);
	fuente2=TTF_OpenFont("./Fuentes/DBJ.ttf",TAM2);
	fuente3=TTF_OpenFont("./Fuentes/DBJ.ttf",TAM3);

	fuenteMB_14=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",14);
	fuenteMB_16=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",16);
	fuenteMB_18=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",18);
	fuenteMB_22=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",22);
	fuenteMB_40=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",30);
	fuenteMB_180=TTF_OpenFont("./Fuentes/SuperMarioBros.ttf",180);


	if(!fuente1 || !fuente2 || !fuente3)
	{
		cout<<"No se pudieron cargar las fuentes."<<endl;
		pthread_exit((void*)1);
	}

	rect.x=0;
	rect.y=0;
	rect.w=0;
	rect.h=0;
	//defino los colores a usar para las fuentes
	colorfuente.r=40;
	colorfuente.g=160;
	colorfuente.b=141;
	colorfuente2.r=250;
	colorfuente2.g=00;
	colorfuente2.b=0;
	colorFuenteAmarillo.r=200;
	colorFuenteAmarillo.g=200;
	colorFuenteAmarillo.b=0;
	colorFuenteAzul.r=70;
	colorFuenteAzul.g=60;
	colorFuenteAzul.b=220;
	colorFuenteBlanco.r=255;
	colorFuenteBlanco.g=255;
	colorFuenteBlanco.b=255;
}


void * escucharConexiones(void *arg){
	int listen_socket, conSocket, byte;
	unsigned short int listen_port = 0;
	unsigned long int listen_ip_address = 0;
	struct sockaddr_in listen_address, con_address;
	socklen_t con_addr_len;
	char buf[TAMBUF];
	//cout << "Lenght = " << (sizeof(torneo->partidas)/sizeof(*torneo->partidas)) << endl; //muestro el espacio reservado para array de partidas

	//Creamos el Socket de Escucha
	listen_socket = socket(AF_INET, SOCK_STREAM, 0);
	//Asigno dirección y configuracion.puerto_escucha
	bzero(&listen_address, sizeof(listen_address));
	listen_address.sin_family = AF_INET;
	listen_port = htons(config.getPuerto());
	listen_address.sin_port = listen_port;
	listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
	int var=1;
	setsockopt(listen_socket,SOL_SOCKET,SO_REUSEADDR,&var,sizeof(int));
	bind(listen_socket,(struct sockaddr*)&(listen_address), sizeof(struct sockaddr));

	//Comenzamos a escuchar conexiones
	if( (listen(listen_socket,MAXQ)) < 0 ){
		fprintf(stderr , "Error al escuchar conexiones.\n");
		exit(0);
	}

	char nombrebuf[TAMBUF];


	//Aceptamos conexiones
	while(true)
	{

		printf("Esperando conexiones...\n");
		conSocket = accept(listen_socket, (struct sockaddr *)(&con_address), &con_addr_len);
		fflush(stdin);
		fflush(stdout);
		printf("Se ha conectado un jugador. Número de Socket: %d\n",conSocket);
		strcpy(nombrebuf,"");

		if(flag_conexiones==1){
			//recibo el nombre del jugador
			if ((byte=recv(conSocket, nombrebuf, TAMBUF, 0)) <=0){
					printf("Error - al recibir nombre de cliente \n");
			}
			// nombrebuf[byte]='\0';
			printf ("Nombre recibido: %s\n", nombrebuf);

			sem_wait(semMemoria);

			torneo->jugador[indice].socket=conSocket;
			torneo->jugador[indice].puntaje=0;
			strcpy(torneo->jugador[indice].nombre,strcat(nombrebuf, "\0"));
			//strcat(torneo->jugador[indice].nombre, nombrebuf);
			torneo->jugador[indice].cantPartidas = 0;
			torneo->jugador[indice].disponible = 1;
			torneo->jugador[indice].id=indice;
			torneo->cantJugadores++;
			torneo->jugador[indice].conectado=1;

			//strcpy(torneo->jugador[indice].ip,inet_ntoa(con_address.sin_addr));
			//sprintf(torneo->jugador[indice].puerto, "%d", (int)ntohs(con_address.sin_port));
			sem_post(semMemoria);
			//Incremento la posicion del vector de jugadores del torneo.
			indice++;
			////////////// muestro jugadores en array (verificacion)
//			for(i=0;i< torneo->cantJugadores;i++)
//			{
//				printf("cantidad de partidas: %d\n",torneo->jugador[i].cantPartidas);
//				printf("estoy conectado: %d\n",torneo->jugador[i].conectado);
//				printf("estoy disponible: %d\n",torneo->jugador[i].disponible);
//				printf("mi id: %d\n",torneo->jugador[i].id);
//				printf("Nombre: %s\n",torneo->jugador[i].nombre);
//				printf("Posicione en el torneo: %d\n",torneo->jugador[i].posicionEnTorneo);
//				printf("Puntaje: %d\n",torneo->jugador[i].puntaje);
//				printf("Socket: %d\n",torneo->jugador[i].socket);
//				printf("\n-------------------------------------------------\n");
//			}
		}
	}
	pthread_exit((void*)1);
	return 0;
}
void rechazarJugador(int conSocket)
{
	char buf[TAMBUF];
	char verResp[TAMBUF];
	int tamEnvio;

	buf[TAMBUF] = '\0';
	memset(&buf,'\0',TAMBUF);
	verResp[TAMBUF] = '\0';
	memset(&verResp,'\0',TAMBUF);

	printf("se acepta  jugador con el socket:  %d\n", conSocket);
	//strcpy(buf,"");
	strncpy( buf , "no",TAMBUF);
	puts(buf);

	//	do{
			tamEnvio=send(conSocket,(char*)buf,TAMBUF,0);
	//		recv(conSocket,(char*)verResp,TAMBUF,0);
	//		tamEnvio=send(conSocket,(char*)verResp,TAMBUF,0);
	//	}
	//	while(strncmp(buf,verResp,TAMBUF)!=0);

	printf("linea 338 envio aceptar jugador tamaño de envio: %d\n",tamEnvio);
	close(conSocket);
}

void aceptarJugador(int conSocket)
{
	char buf[TAMBUF];
	char verResp[TAMBUF];
	int tamEnvio;

	buf[TAMBUF] = '\0';
	memset(&buf,'\0',TAMBUF);
	verResp[TAMBUF] = '\0';
	memset(&verResp,'\0',TAMBUF);

	printf("se acepta  jugador con el socket:  %d\n", conSocket);
	//strcpy(buf,"");
	strncpy( buf , "si",TAMBUF);
	puts(buf);

	//	do{
			tamEnvio=send(conSocket,(char*)buf,TAMBUF,0);
			tamEnvio=send(conSocket,(char*)buf,TAMBUF,0);
			tamEnvio=send(conSocket,(char*)buf,TAMBUF,0);
	//		recv(conSocket,(char*)verResp,TAMBUF,0);
	//		tamEnvio=send(conSocket,(char*)verResp,TAMBUF,0);
	//	}
	//	while(strncmp(buf,verResp,TAMBUF)!=0);

	printf("linea 338 envio aceptar jugador tamaño de envio: %d\n",tamEnvio);
}
void mensajeAJugador(const char* msj, int conSocket){
	char mensaje[TAMBUF];
	char verResp[TAMBUF];
	int tamEnvio;

	mensaje[TAMBUF] = '\0';
	memset(&mensaje,'\0',TAMBUF);
	verResp[TAMBUF] = '\0';
	memset(&verResp,'\0',TAMBUF);

	//strcpy(mensaje,msj);
	//bzero(mensaje,TAMBUF);
	strncpy(mensaje,msj,TAMBUF);
	//sprintf(mensaje,"%s",msj);
	printf("ESTE ES EL MENSAJE QUE MANDO CON EL RESULTADO DE TORNEO mensaje: %s\n",mensaje);
	usleep(10000);
	fflush(stdin);
	fflush(stdout);
	//	do{
			tamEnvio= send(conSocket,(char*)mensaje,TAMBUF,0);
			tamEnvio= send(conSocket,(char*)mensaje,TAMBUF,0);
			tamEnvio= send(conSocket,(char*)mensaje,TAMBUF,0);
	//		recv(conSocket,(char*)verResp,TAMBUF,0);
	//		tamEnvio= send(conSocket,(char*)verResp,TAMBUF,0);
	//	}
	//	while(strncmp(mensaje,verResp,TAMBUF)!=0);

	printf("linea 349 envio mensajeAJugador() tamaño de envio: %d\n",tamEnvio);
	puts("ENVIO FIN PARTIDA DESDE SERVIDOR DE TORNEO--------------------------------------");



}
void administrarPartidas()
{
	int id1, id2, i;
	int pendientes=0;

	//printf("Cantidad de Partidas: %d\n",cant_partidas);
	usleep(8000);
	for (i=0;i<cant_partidas;i++)
	{
		if (torneo->partidas[i].pid==0)
		{
			sem_wait(semMemoria);
			id1 = torneo->partidas[i].jugador1;
			id2 = torneo->partidas[i].jugador2;

			//Si los jugadores están conectados y disponibles lanza la partida.
			if (torneo->jugador[id1].disponible==1 && torneo->jugador[id2].disponible==1 && torneo->jugador[id1].conectado==1 && torneo->jugador[id2].conectado==1)
			{
				pendientes=1;
				torneo->jugador[id1].disponible=0;
				torneo->jugador[id2].disponible=0;
				torneo->jugador[id1].cantPartidas++;
				torneo->jugador[id2].cantPartidas++;
				printf ("Lanzando partida %d, %d - %d\n", i, id1, id2);
				sem_post(semMemoria);
				lanzarPartidas(torneo->jugador[id1].socket, torneo->jugador[id2].socket, i);

			}
			else{
				sem_post(semMemoria);
			}
		}

	} //termina el for
}
//Lanzar Partidas Genera los procesos hijos que seran los servidores de partida.
void lanzarPartidas (int socket1, int socket2, int cant_partidas)
{
	int child;
	char valor1[10], valor2[10], valor3[10], JugadoresNombres[41];//JugadoresNombres contiene los nombres de ambos jugadores separados por un espacio
	child = fork();
	printf ("Funcion lanzando partida hijo\n");
	if (child == -1)
		puts("Error creando Servidor de Partida.\n");
	else
	{
		if (child == 0)
		{
			sprintf (valor1, "%d", socket1);
			sprintf (valor2, "%d", socket2);
			sprintf (valor3, "%d", cant_partidas);
			sleep(1);

			printf("Antes ESTOY POR MANDAR NOMBRES  \n");
			sem_wait(semMemoria);
			printf("ESTOY POR MANDAR NOMBRES  ");

			//envio los nombres de los jugadores a los clientes para que los imprima en pantalla.
			envioNombreJugadoresACliente(socket1,socket2
					,torneo->jugador[torneo->partidas[cant_partidas].jugador1].nombre
					,torneo->jugador[torneo->partidas[cant_partidas].jugador2].nombre);
			sem_post(semMemoria);
			//Ejecutamos el servidor de Partida
			//if (execl(PATH_SP, "ServerMatch", valor1, valor2, valor3, NULL)==-1) //chequeamos si el comando es válido en el shell
			//printf ("Error al ejecutar el Servidor de Partida %d", i);
			printf("El pid de la partida es %d \n", getpid());
			if (execlp(PATH_SP, "ServerMatch", NULL)==-1)
				printf ("Error al ejecutar el Servidor de Partida %d", cant_partidas+1);
		}
		else
		{	//Proceso padre;
			sem_wait(semMemoria);
			torneo->partidas[cant_partidas].pid = child;
			sem_post(semMemoria);
		}
	}
}//envio los nombres de los dos jugadores al cliente 1 para que pueda imprimirlos por pantalla
void envioNombreJugadoresACliente(int socket1,int socket2,const char *jugador1,const char *jugador2){
	//envio los nombres de los dos jugadores al cliente 1 para que pueda imprimirlos por pantalla
	int tamEnvio=0;
	char jugadores[TAMBUF];
	char verResp[TAMBUF];

	jugadores[TAMBUF]='\0';
	memset(&jugadores,'\0',TAMBUF);
	verResp[TAMBUF]='\0';
	memset(&verResp,'\0',TAMBUF);

	//strncpy(jugadores, "",sizeof(jugadores));
    strncpy(jugadores,jugador1,TAMBUF);
	strncat(jugadores," ",TAMBUF);
    strncat(jugadores, jugador2,TAMBUF);
	strncat(jugadores," ",TAMBUF);

	printf("TAMAÑO CADENA %d",strlen(jugadores));


	//	do{
			tamEnvio= send(socket1,(char*)jugadores,TAMBUF,0);
			tamEnvio= send(socket1,(char*)jugadores,TAMBUF,0);
			tamEnvio= send(socket1,(char*)jugadores,TAMBUF,0);
	//		recv(socket1,(char*)verResp,TAMBUF,0);
	//		tamEnvio= send(socket1,(char*)verResp,TAMBUF,0);
	//	}
	//	while(strncmp(jugadores,verResp,TAMBUF)!=0 && tamEnvio != -1);


	printf("send envioNombreJugadores, jugador1y2, tamaño: %d\n",tamEnvio);
	printf("send envioNombreJugadores, jugador1y2, nombres: %s\n",jugadores);
	//tamEnvio=send(socket1,jugador2,20,0);
	//printf("send envioNombreJugadores, jugador2, tamaño: %d\n",tamEnvio);
	//envio los nombres de los dos jugadores al cliente 2 para que pueda imprimirlos por pantalla

	verResp[TAMBUF]='\0';
	memset(&verResp,'\0',TAMBUF);

	//	do{
			tamEnvio=send(socket2,(char*)jugadores,TAMBUF,0);
			tamEnvio=send(socket2,(char*)jugadores,TAMBUF,0);
			tamEnvio=send(socket2,(char*)jugadores,TAMBUF,0);
	//		recv(socket2,(char*)verResp,TAMBUF,0);
	//		tamEnvio=send(socket2,(char*)verResp,TAMBUF,0);
	//	}
	//	while(strncmp(jugadores,verResp,TAMBUF)!=0 && tamEnvio != -1);


	printf("send envioNombreJugadores, jugador1y2, tamaño: %d\n",tamEnvio);
	//tamEnvio=send(socket2,jugador2,20,0);
	//printf("send envioNombreJugadores, jugador2, tamaño: %d\n",tamEnvio);
}

void reLanzarPartidas (int socket1, int socket2, int pos)
{
	int child;

	child = fork();
	printf ("Funcion lanzando partida hijo\n");
	if (child == -1)
		puts("Error creando Servidor de Partida.\n");
	else
	{
		if (child == 0)
		{

			printf("El pid de la partida es %d \n", getpid());
			if (execlp(PATH_SP, "ServerMatch", NULL)==-1)
				printf ("Error al ejecutar el Servidor de Partida %d", pos+1);
		}
		else
		{	//Proceso padre;
			sem_wait(semMemoria);
			torneo->partidas[pos].pid = child;
			sem_post(semMemoria);
		}
	}
}

void inicializarPosiciones(){
	int i;
	for(i=0;i<torneo->cantJugadores;i++){
		if(torneo->cantJugadores >= 2 && torneo->cantJugadores <= 3){
			torneo->jugador[i].posicionEnTorneo = 2;
		}
		if(torneo->cantJugadores >= 4 && torneo->cantJugadores <= 5){
			torneo->jugador[i].posicionEnTorneo = 3;
		}
		if(torneo->cantJugadores >= 6 && torneo->cantJugadores <= 7){
			torneo->jugador[i].posicionEnTorneo = 4;
		}
		if(torneo->cantJugadores >= 6 && torneo->cantJugadores <= 9){
			torneo->jugador[i].posicionEnTorneo = 4;
		}
		if(torneo->cantJugadores >= 10 && torneo->cantJugadores <= 17){
			torneo->jugador[i].posicionEnTorneo = 5;
		}
		if(torneo->cantJugadores >= 18){
			torneo->jugador[i].posicionEnTorneo = 6;
		}
	}
}
// Parametros armarPartidas:
// 1 - armo partidas por primera vez.
// 0 - vuelvo a rearmar partidas tomando solo los ganadores (disponibles).
void armarPartidas(int accion)
{

	puts("Armando las partidas.");

	if(accion == 1){
		int cant, i;
		//la primera partida que generamos.
		if (cant_partidas==1)
			if(gettimeofday(&t_inicio, NULL)!=0)
				cout << "Error al obtener la hora de inicio." <<endl;

		sem_wait(semMemoria);
		inicializarPosiciones();
		cant = torneo->cantJugadores-1;
		sem_post(semMemoria);
		printf("Cantidad de Jugadores: %d - %d\n", torneo->cantJugadores, cant);
		if(torneo->cantJugadores > 1){
			//en el 1er jugador no entra xq cant es cero
			for(i=0; i <= (cant/2); i++)
			{
				//printf("Generando Partida %d, %d - %d\n", cant_partidas, cant, torneo->jugador[i].id);
				if(i==cant-i)
				{
					sem_wait(semMemoria);
					//mandar mensaje al torneo->jugador[i].id que es el cliente que quedo afuera
					rechazarJugador(torneo->jugador[i].socket);
					torneo->jugador[i].conectado=0;
					printf("Se rechazo al jugador %s, id %d, socket %d\n",torneo->jugador[i].nombre,torneo->jugador[i].id,torneo->jugador[i].socket);
					sem_post(semMemoria);
				}
				else
				{
					sem_wait(semMemoria);
					torneo->partidas[cant_partidas].jugador1 = torneo->jugador[i].id;
					torneo->partidas[cant_partidas].jugador2 = torneo->jugador[cant-i].id;
					torneo->partidas[cant_partidas].pid = 0;
					torneo->partidas[cant_partidas].jugadorGanador = 0;
					torneo->partidas[cant_partidas].terminoPartida = 0;
					puts("Armando la partida:");
					aceptarJugador(torneo->jugador[i].socket);
					printf("jugador aceptado %s, id %d, socket %d\n",torneo->jugador[i].nombre,torneo->jugador[i].id,torneo->jugador[i].socket);
					aceptarJugador(torneo->jugador[cant-i].socket);
					printf("jugador aceptado %s, id %d, socket %d\n",torneo->jugador[cant-i].nombre,torneo->jugador[cant-i].id,torneo->jugador[cant-i].socket);
					cant_partidas++;
					torneo->cantPartidas++;
					sem_post(semMemoria);
				}
				printf("CANTIDAD DE PARTIDAS ARMADAS: %d\n",torneo->cantPartidas);
				if(gettimeofday(&t_actual, NULL)!=0)
					cout << "Error al obtener la hora de inicio." <<endl;
			}//FINALIZA EL FOR
			sem_wait(semMemoria);
			cant_partidasRearmadas = torneo->cantPartidas;
			printf("CANTIDAD DE PARTIDAS RE-ARMADAS: %d\n",cant_partidasRearmadas);
			sem_post(semMemoria);
		}
	}//FINALIZA EL IF DE LA PRIMERA RONDA DE PARTIDAS
	else{   //MANEJO EL ARMADO DE LAS DEMAS PARTIDAS. ES CUANDO MANDAN 0.
		int cant,
			i,
			recorrido=0;
		sem_wait(semMemoria);
		cant =  cant_partidas-1;
		sem_post(semMemoria);

		for(i=0; i <= (cant); i++)   //en el 1er jugador no entra xq cant es cero
		{
			if(torneo->partidas[i].terminoPartida == 0 && (torneo->jugador[torneo->partidas[i].jugador1].disponible == 1 || torneo->jugador[torneo->partidas[i].jugador2].disponible == 1)){

				if(i==cant-i){  //Son impares el jugador pasa a la siguiente ronda directamente.
					sem_wait(semMemoria);
					if(torneo->jugador[torneo->partidas[i].jugador1].disponible == 1)
						torneo->jugador[torneo->partidas[i].jugador1].posicionEnTorneo --;
					if(torneo->jugador[torneo->partidas[i].jugador2].disponible == 1)
						torneo->jugador[torneo->partidas[i].jugador2].posicionEnTorneo --;
					sem_post(semMemoria);
					if(torneo->jugador[torneo->partidas[i].jugador1].disponible == 1)
						printf("Partidas impares pasa a la siguiente ronda %s \n",torneo->jugador[torneo->partidas[i].jugador1].nombre);
					if(torneo->jugador[torneo->partidas[i].jugador2].disponible == 1)
						printf("Partidas impares pasa a la siguiente ronda %s \n",torneo->jugador[torneo->partidas[i].jugador2].nombre);

				}
				else
				{

					int j;
					for(j=cant-recorrido;j>i;j--){
							recorrido++;

							if(torneo->partidas[j].terminoPartida == 0 && (torneo->jugador[torneo->partidas[j].jugador1].disponible == 1 || torneo->jugador[torneo->partidas[j].jugador2].disponible == 1)){
								sem_wait(semMemoria);
								//sem_wait(semPartidas);

								if(torneo->jugador[torneo->partidas[i].jugador1].disponible == 1){
									torneo->partidas[cant_partidas].jugador1 = torneo->partidas[i].jugador1;
									aceptarJugador(torneo->jugador[torneo->partidas[i].jugador1].socket);
									//torneo->jugador[torneo->partidas[i].jugador1].disponible=0;
								}
								else{
									torneo->partidas[cant_partidas].jugador1 = torneo->partidas[i].jugador2;
									aceptarJugador(torneo->jugador[torneo->partidas[i].jugador2].socket);
									//torneo->jugador[torneo->partidas[i].jugador2].disponible=0;
								}

								if(torneo->jugador[torneo->partidas[j].jugador1].disponible == 1){
									torneo->partidas[cant_partidas].jugador2 = torneo->partidas[j].jugador1;
									aceptarJugador(torneo->jugador[torneo->partidas[j].jugador1].socket);
									//torneo->jugador[torneo->partidas[j].jugador1].disponible=0;
								}
								else{
									torneo->partidas[cant_partidas].jugador2 = torneo->partidas[j].jugador2;
									aceptarJugador(torneo->jugador[torneo->partidas[j].jugador2].socket);
									//torneo->jugador[torneo->partidas[j].jugador2].disponible=0;
								}

								torneo->partidas[cant_partidas].jugadorGanador = 0;
								torneo->partidas[cant_partidas].pid = 0;
								torneo->partidas[cant_partidas].terminoPartida = 0;
								torneo->partidas[i].terminoPartida = 1;
								torneo->partidas[j].terminoPartida = 1;


								printf("Jugador 1: %d %s\n", torneo->partidas[cant_partidas].jugador1,torneo->jugador[torneo->partidas[cant_partidas].jugador1].nombre);
								printf("Jugador 2: %d %s\n", torneo->partidas[cant_partidas].jugador2,torneo->jugador[torneo->partidas[cant_partidas].jugador2].nombre);

								cant_partidas++;
								torneo->cantPartidas++;

								sem_post(semMemoria);
								//sem_post(semPartidas)

								break;
							}
					}
				}

				//id2=torneo->jugador[i].id;

				if(gettimeofday(&t_actual, NULL)!=0)
					cout << "Error al obtener la hora de inicio." <<endl;

			}
		}//fin del for
		printf("CANTIDAD DE PARTIDAS ARMADAS HASTA AHORA: %d\n",cant_partidas);
	}//FINALIZA EL else
	//asigno memoria para la nueva partida
	//torneo->partidas = (t_partida *) realloc (torneo->partidas, cant_partidas);
}
//espera a todas las partidas que aún están corriendo, son las que no tiene pid = 0.
void esperarPartidas()
{
	int i,pid,partidaTerminada,cantidadJugadores=0;
	sem_wait(semMemoria);
	cantidadJugadores =torneo->cantJugadores;
	sem_post(semMemoria);
	if(cantidadJugadores > 1){
		while(1){

			while(senalHijos < cant_partidas){
				for (i=0;i<cant_partidas;i++)
				{
					pid=0;
					sem_wait(semMemoria);
					partidaTerminada=torneo->partidas[i].terminoPartida;
					pid=torneo->partidas[i].pid;
					sem_post(semMemoria);

					if(pid>0 && partidaTerminada == 0){// && torneo->partidas[i].terminoPartida==1){
						usleep(8000);
						waitpid(pid, &status, 0);
					}

				}
			}
			sleep(3); //Espero para que todos los clientes lleguen bien el recv.
			printf("CANT PARTIDAS POR AHORA %d \n",cant_partidasRearmadas);
			if(cant_partidasRearmadas<=1){  //Ya no tengo mas partidas para armar.
				puts("ANTES DE MOSTRAR AL GANADOR");
				//sleep(1.5);
				sem_wait(semPartidas);
				informarResultadoAClientes();
				sem_post(semPartidas);
				//al finalizar el torneo, el thread que dibuja las pantallas se actualiza con las posiciones finales del torneo
				//el torneo puede finalizar porque terminaron todas las partidas (aca) o porque se acabo el tiempo total de torneo.
				finalizado=1; //finalizó el torneo.
				printf("Finalizo el torneo no hay mas partidas para armar\n");
				return;
			}

			cant_partidasRearmadas = (cant_partidasRearmadas % 2 == 0?cant_partidasRearmadas / 2:((cant_partidasRearmadas / 2)+1) );

			printf("HAY ESTAS PARTIDAS %d \n",cant_partidasRearmadas);
			//armo las partidas nuevas una vez finalizadas las anteriores
			sem_wait(semPartidas);
			armarPartidas(0);
			//Se ejecutan las nuevas partidas.
			administrarPartidas();
			sem_post(semPartidas);
			//vuelvo a esperar por otras partidas si es que hay.
			//esperarPartidas();
		}

	}
}

void informarResultadoAClientes(){
	//al finalizar el torneo, se informa a cada cliente
	//(jugador) cual fue la posicion final que obtuvo en el torneo
	int i,j;
	char temp[TAMBUF];
	char nombreGanadorYPos[TAMBUF];
	char posicionEnTorneo[TAMBUF];
	nombreGanadorYPos[TAMBUF]='\0';
	memset(&nombreGanadorYPos,'\0',TAMBUF);

	posicionEnTorneo[TAMBUF]='\0';
	memset(&posicionEnTorneo,'\0',TAMBUF);

	sem_wait(semMemoria);

	//A cada jugador se le manda quien gano. Para eso busco el ganador.
	for(j=0;j<torneo->cantJugadores;j++){
		if(torneo->jugador[j].conectado != 0 && torneo->jugador[j].posicionEnTorneo == 1){
		    strncpy(nombreGanadorYPos,"Ganador: ",TAMBUF);
			strncat(nombreGanadorYPos, torneo->jugador[j].nombre,TAMBUF);
			//strncat(nombreGanadorYPos,"   Mi Posicion: ",TAMBUF);
			strncat(nombreGanadorYPos,"*",TAMBUF);
		    strncpy(temp,nombreGanadorYPos,TAMBUF);
			break;
		}
	}

	//manda posición de cada jugador.
	for(i=0;i<torneo->cantJugadores;i++){
		if(torneo->jugador[i].conectado != 0){
			sprintf (posicionEnTorneo, "%d", torneo->jugador[i].posicionEnTorneo);
			strncpy(posicionEnTorneo,posicionEnTorneo, TAMBUF);

		    strncat(nombreGanadorYPos,posicionEnTorneo,TAMBUF);
			strncat(nombreGanadorYPos,"*",TAMBUF);

			mensajeAJugador(nombreGanadorYPos,torneo->jugador[i].socket);

			strncpy(nombreGanadorYPos,temp,TAMBUF);

			//mensajeAJugador(nombreGanadorYPos,torneo->jugador[i].socket);

			printf("SE INFORMO LA POSICION EN TORNEO AL JUGADOR: %s, id: %d\n",torneo->jugador[i].nombre,i);
		}
	}

	sem_post(semMemoria);
}

void * dibujarPantalla(void *arg){
	int cargarTorneoFinalizado = 1;
	//cargarPresentacion();
	while(true){

		if(!finTiempoDeconexion && !finalizado){
			cargaTitulos(1);
		}
		else{
			if(!finalizado){
				mostrarPartidasArmadas();
			}
			else{
				//Se carga la pantalla torneo finalizado la primera vez.
				if(cargarTorneoFinalizado==1){

					cargarPresentacionTorneoFinalizado();
					cargarTorneoFinalizado=0;
				}

				mostrarResultadoFinalDeTorneo();
			}
		}
	}
	return 0;
}

void mostrarResultadoFinalDeTorneo(){
	int i;
	char valor [200];

	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
	rect.x=0;
	rect.y=0;
	rect.w=imagen->w;
	rect.h=imagen->h;
	SDL_BlitSurface(imagen, NULL, screen, &rect );

	strcpy(valor,"");
	int desplazamiento =0;
	sem_wait(semMemoria);
	int p=0; //con esta variable tenemos los jugadores que realmente jugaron partidas, omitiendo los que no se rechazaron.
	for(i=0;i<torneo->cantJugadores;i++)
	{
		if(torneo->jugador[i].conectado != 0){
			desplazamiento = p*35;
			posicionY = limitePantallaTextoFinTorneoInferior + desplazamiento;

			sprintf(valor,"%d - %s ",torneo->jugador[i].posicionEnTorneo,torneo->jugador[i].nombre);

			if(posicionY < 440 && posicionY > 180){
				imprimirEnPantalla2(valor,200,posicionY,colorFuenteBlanco,fuenteMB_22);

			}
			strcpy(valor,"");
			p++;
		}
	}
	//LOS LIMETES DE ESCRITURA EN PANTALLA SON ENTRE 200 Y 440 EN Y ; PARA X 10 Y 180
	limitePantallaTextoFinTorneoInferior-=20;
	// me aseguro que pasaron todos los jugadores por dentro de los limites de impresion en pantalla
	if(limitePantallaTextoFinTorneoInferior < 200-(p*35))
		limitePantallaTextoFinTorneoInferior=440;

	limitePantallaTextoFinTorneoSuperior -= 20;
	if(limitePantallaTextoFinTorneoSuperior < 0)
		limitePantallaTextoFinTorneoSuperior = 200;

	sem_post(semMemoria);

	//imprimo el mono
	monoIzqDer = monoIzqDer==0?1:0;
	if(monoIzqDer)
		imgMono=IMG_Load("./Imagenes/monoD.png");
	else
		imgMono=IMG_Load("./Imagenes/monoI.png");
	imgMono=SDL_DisplayFormatAlpha(imgMono);
	rectMono.x=530;
	rectMono.y=180;
	rectMono.w=imgMono->w;
	rectMono.h=imgMono->h;
	SDL_BlitSurface(imgMono, NULL, screen, &rectMono );
	SDL_Flip(screen);
	sleep(1);
}
void cargarPresentacion()
{
	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));

	imagen=SDL_LoadBMP("./Imagenes/EsperandoConexiones.bmp");
	imagen=SDL_DisplayFormatAlpha(imagen);
	rect.x=0;
	rect.y=0;
	rect.w=imagen->w;
	rect.h=imagen->h;
	SDL_BlitSurface(imagen, NULL, screen, &rect );
	SDL_Flip(screen);
	sleep(1);
}
void cargarPresentacionPartidas()
{
	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));

	imagen=SDL_LoadBMP("./Imagenes/AdministradorDePartidas.bmp");
	imagen=SDL_DisplayFormatAlpha(imagen);
	rect.x=0;
	rect.y=0;
	rect.w=0;
	rect.h=0;
	SDL_BlitSurface(imagen, NULL, screen, &rect );
	SDL_Flip(screen);

	sleep(1);
}
void cargarPresentacionTorneoFinalizado()
{
	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));

	imagen=SDL_LoadBMP("./Imagenes/TorneoFinalizado.bmp");
	imagen=SDL_DisplayFormatAlpha(imagen);
	rect.x=0;
	rect.y=0;
	rect.w=0;
	rect.h=0;
	SDL_BlitSurface(imagen, NULL, screen, &rect );
	SDL_Flip(screen);

	sleep(1);
}
void pantallaPresentacion(){
	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));

		imagen=SDL_LoadBMP("./Imagenes/dk_ini.bmp");
		imagen=SDL_DisplayFormatAlpha(imagen);
		rect.x=0;
		rect.y=0;
		rect.w=imagen->w;
		rect.h=imagen->h;
		SDL_BlitSurface(imagen, NULL, screen, &rect );
		SDL_Flip(screen);
	sleep(1);
}
void cargaTitulos(int seleccion)
{
		char valor [200];
		int tiempoRestanteConexion;

		SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));

		rect.x=0;
		rect.y=0;
		rect.w=0;
		rect.h=0;
		SDL_BlitSurface(imagen, NULL, screen, &rect );

		sem_wait(semMemoria);
		tiempoRestanteConexion = torneo->tiempo_espera_conex_max - torneo->t_chequeo;
		sem_post(semMemoria);

		if(tiempoRestanteConexion > 0){
			//sprintf (valor, "Esperando conexiones: %d segundos",  tiempoRestanteConexion>=0?(int)tiempoRestanteConexion:0);
			sprintf (valor, " %2d ",  tiempoRestanteConexion>=0?(int)tiempoRestanteConexion:0);
			ttext=TTF_RenderText_Solid(fuenteMB_180,valor,colorFuenteBlanco);
			rect.x=140;
			rect.y =200;
			SDL_BlitSurface(ttext,NULL,screen,&rect);
			y+=TAM2*3; //incremento la posicion de y

			SDL_Flip(screen);
			SDL_Delay(900);
		}
		else{
			sprintf(valor, "ARMANDO LAS PARTIDAS...");
			ttext=TTF_RenderText_Solid(fuenteMB_40,valor,colorFuenteBlanco);
			rect.x=120;
			rect.y =230;
			SDL_BlitSurface(ttext,NULL,screen,&rect);
			y+=TAM2*3; //incremento la posicion de y
			SDL_Flip(screen);
			sleep(2);

			cargarPresentacionPartidas();
		}

		recargarPantalla();
}

int SDL_WaitEventTimeout(SDL_Event * event, int timeout)
{
    Uint32 expiration;

    if (timeout > 0)
        expiration = SDL_GetTicks() + timeout;

     while (1) {
         SDL_PumpEvents();
         switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS))
         {
         case 1:
             return 1;
         case 0:
            SDL_Delay(10);
            if (timeout == 0 || (timeout > 0 && SDL_GetTicks() >= expiration))
            {
            	refrescar=true;
                return 0;
            }
            else
               SDL_Delay(10);
            	break;
         }
     }
     return 0;
}

//se utiliza para actualizar cuando ingresen nuevos jugadores...
void recargarPantalla()
{
//	refrescar=true;
}

int getFin()
{
	return finalizado==1;
}
void * monitorTeclas(void *arg)
{
	while(true){
		SDL_WaitEvent(&event); // se queda esperando por algun evento. no consume cpu
		SDL_PollEvent(&event);
		if (event.key.keysym.sym==SDLK_ESCAPE  || event.type == SDL_QUIT)
		{

				liberarRecursos();
				pthread_cancel(threadDibuja);
				pthread_cancel(threadEscucha);
				pthread_cancel(threadTiempo);
				pthread_cancel(threadMonitorearServidor);
				//kill(gettid(),9);
				exit(0);
		}
	}
	return 0;
}

//ejecuta el código cada 1 segundo.
void * controlarTiempo(void *arg){
	int tiempoChequeoActual=0;

	while (getFin()==0)
	{

		sem_wait(semMemoria); //bloqueo memoria compartida

		if (torneo->t_chequeo > config.getTiempoTorneo()*60) //tiempo en segundos del torneo en total.
			finalizado=1;

		sem_post(semMemoria); //libero memoria compartida
		sleep(1);
		sem_wait(semMemoria); //vuelvo a bloquear
		torneo->t_chequeo++;
		tiempoChequeoActual =torneo->t_chequeo;
		sem_post(semMemoria);

		//printf ("Tiempo Torneo %d\n", torneo->t_chequeo);
		//printf("fin tiempo conexion: %d\n",finTiempoDeconexion);
		if (tiempoChequeoActual > config.getTiempoEsperaConexMax() && finTiempoDeconexion==0)
		{
			finTiempoDeconexion=1;
			pthread_cancel(threadEscucha);
			puts("finalizo el tiempo de conexion.");
			sem_wait(semPartidas);
			armarPartidas(1);   //mando 1 para indicarle que es la primera RONDA de juego si es que hay mas de una.
			sem_post(semPartidas);

		}

	}
return 0;
}

void mostrarPartidasArmadas(){
	int i;
	char valor [200];

	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
	rect.x=0;
	rect.y=0;
	rect.w=imagen->w;
	rect.h=imagen->h;
	SDL_BlitSurface(imagen, NULL, screen, &rect );

	sem_wait(semMemoria);
	sprintf (valor, "Tiempo: %d / %d min", torneo->t_chequeo/60, torneo->tiempo_torneo);
	sem_post(semMemoria);

	imprimirEnPantalla2(valor,160,10,colorFuenteAzul,fuenteMB_22);
	strcpy(valor,"");

	switch(config.getNivelDificultad()){
		case 1: strcpy(valor,"(Nivel Brasil)");
				break;
		case 2: strcpy(valor,"(Nivel Normal)");
				break;
		case 3: strcpy(valor,"(Nivel Extreme)");
	}
	imprimirEnPantalla2(valor,420,10,colorFuenteAzul,fuenteMB_22);
	strcpy(valor,"");

	int desplazamiento =0;
	sem_wait(semMemoria);
	for(i=0;i<cant_partidas;i++)
	{
		desplazamiento = i*35;
		sprintf(valor,"%d) %s VS %s - Ganador: %s",i+1, torneo->jugador[torneo->partidas[i].jugador1].nombre,torneo->jugador[torneo->partidas[i].jugador2].nombre, (torneo->partidas[i].jugadorGanador)==0?" JUGANDO ": (torneo->partidas[i].jugadorGanador)==1?" JUGADOR 1 ":" JUGADOR 2 ");
		posicionY = limitePantallaTextoFinTorneoInferior+desplazamiento;
		if(posicionY < 440 && posicionY > 180)
			imprimirEnPantalla2(valor,20,posicionY,colorFuenteBlanco,fuenteMB_18);
		strcpy(valor,"");
	}
	if(cant_partidas < 1){
		desplazamiento = i*80;
		sprintf(valor,"NO SE PUDIERON ARMAR PARTIDAS.");
		imprimirEnPantalla(valor,60,220,colorFuenteBlanco,fuenteMB_22);
		strcpy(valor,"");
	}
	//LOS LIMETES DE ESCRITURA EN PANTALLA SON ENTRE 200 Y 440 EN Y ; PARA X 10 Y 180
	limitePantallaTextoFinTorneoInferior-=20;
	// me aseguro que pasaron todos los jugadores por dentro de los limites de impresion en pantalla
	if(limitePantallaTextoFinTorneoInferior < 170-(torneo->cantPartidas * 20))
		limitePantallaTextoFinTorneoInferior=440;

	sem_post(semMemoria);

	//imprimo el mono
	monoIzqDer = monoIzqDer==0?1:0;
	if(monoIzqDer)
		imgMono=IMG_Load("./Imagenes/monoD.png");
	else
		imgMono=IMG_Load("./Imagenes/monoI.png");

	imgMono=SDL_DisplayFormatAlpha(imgMono);
	rectMono.x=530;
	rectMono.y=180;
	rectMono.w=imgMono->w;
	rectMono.h=imgMono->h;
	SDL_BlitSurface(imgMono, NULL, screen, &rectMono );

	SDL_Flip(screen);
	sleep(1);
}
void imprimirEnPantalla2(const char *valor,int x, int y,SDL_Color color,TTF_Font *fuente)
{

	ttext=TTF_RenderText_Blended(fuente,valor,color);
	rect.x=x;
	rect.y=y;
	SDL_BlitSurface(ttext,NULL,screen,&rect);
	y+=TAM2*3;
}
void imprimirEnPantalla(const char *valor,int x, int y,SDL_Color color,TTF_Font *fuente)
{

	ttext=TTF_RenderText_Solid(fuente,valor,color);
	rect.x=x;
	rect.y+=y;
	SDL_BlitSurface(ttext,NULL,screen,&rect);
	y+=TAM2*3;
}

//Capturamos las señales
void capturarSeniales()
{
	struct sigaction act;
	act.sa_sigaction = handler_sigchld;
	//bloqueamos las señales.
	sigfillset(&act.sa_mask);
	act.sa_flags = SA_SIGINFO;
	sigaction(SIGCHLD,&act,NULL);
	signal(SIGINT,SIG_IGN);//handler_signal);
	signal(SIGTERM,SIG_IGN);//handler_signal);
	//signal(SIGSTOP,SIG_IGN);
	//signal(SIGKILL,SIG_IGN);
	signal(SIGABRT,SIG_IGN);
	signal(SIGHUP,SIG_IGN);
	signal(SIGPIPE,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	signal(SIGSEGV,SIG_IGN);
	signal(SIGUSR1,SIG_IGN);
	signal(SIGUSR2,SIG_IGN);
	//GP
	signal(SIGALRM,SIG_IGN);
}
void handler_signal(int sig)
{
	switch(sig){
		case SIGALRM:
			signal(SIGALRM, SIG_IGN);
			time_t rawtime;
			struct tm * tiempo;
			time(&rawtime);
			tiempo = gmtime(&rawtime);
			sem_wait(semMemoria);
			torneo->t_chequeo=tiempo->tm_hour*10000+tiempo->tm_min*100+tiempo->tm_sec;
			//printf ("Tiempo Servidor: %d\n", torneo->t_chequeo);
			sem_post(semMemoria);
			signal(SIGALRM, handler_signal);
			alarm(TORNEO_UP);
			break;
		default:
			//printf ("Señal Recibida %d\n", sig);
			liberarRecursos();
			break;
	}
}
void handler_sigchld(int sig, siginfo_t *info, void *ni)
{
	int pid, i, proceso_monitor;

	switch(info->si_code){

		case CLD_KILLED:
                      
         // maxi verifica si ha muerto el monitor
         // proceso_monitor = 1 muerte de monitor
         //proceso_monitor = verificar_proceso_monitor();
         // ha muerto la partida
         //if( proceso_monitor == 0 )  // maxi
         //{

 			sleep(2);
 			pid = info->si_pid;
			sem_wait(semMemoria);
 			//printf("Recibi del pid: %d\n", pid);
 			for(i=0;i<cant_partidas;i++)
 			{
 				//Bloqueo la memoria compartida

 				if(torneo->partidas[i].pid==pid)
 				{
 		 			printf("Mataron al servidor de partida.\n");
 		 			//le aviso a los clientes que es el fin.
 		 			envio env;
 		 			strcpy(env.identificador,"nue");
 		 		    sprintf(env.tipo_senial, "%d",6); //REINICIO JUEGO;
 		 			//env.tipo_senial = FIN_JUEGO;
 		 			usleep(8000);


 		 			torneo->partidaCaida=1;
 					//le mando fin juego a cada uno de los clientes.
 					send(torneo->jugador[torneo->partidas[i].jugador1].socket,&env,sizeof(env),0);
 					send(torneo->jugador[torneo->partidas[i].jugador2].socket,&env,sizeof(env),0);

 					sem_post(semMemoria);
 					reLanzarPartidas(torneo->jugador[torneo->partidas[i].jugador1].socket,torneo->jugador[torneo->partidas[i].jugador2].socket,i);
 					sem_wait(semMemoria);
 				}

 			}
			sem_post(semMemoria);
//         } // fin if
          waitpid(pid,&status2,0);   // maxi
	     break;

		case CLD_EXITED:
						//NO ANDA ESTO MAXI
                        //proceso_monitor = verificar_proceso_monitor();
                        // ha muerto la partida
                     //if( proceso_monitor == 0 )
                     //{


			sem_wait(semMemoria);
			pid = info->si_pid;
			senalHijos++;
			printf("MURIO LA PARTIDA %d \n\n\n\n\n\n\n\n\n\n",pid);

			for(i=0;i<cant_partidas;i++){
				//Bloqueo la memoria compartida
				if(torneo->partidas[i].pid==pid){
					if(torneo->partidas[i].jugadorGanador==1){
						torneo->jugador[torneo->partidas[i].jugador1].disponible=1;
						torneo->jugador[torneo->partidas[i].jugador1].posicionEnTorneo--;
						//torneo->partidas[i].terminoPartida=1;
						//printf("\n%s estoy disponible \n",torneo->jugador[torneo->partidas[i].jugador1].nombre);
					}
					if(torneo->partidas[i].jugadorGanador==2){
						torneo->jugador[torneo->partidas[i].jugador2].disponible=1;
						torneo->jugador[torneo->partidas[i].jugador2].posicionEnTorneo--;
						//torneo->partidas[i].terminoPartida=1;
						//printf("\n%s estoy disponible \n",torneo->jugador[torneo->partidas[i].jugador2].nombre);
					}
					torneo->partidas[i].pid=-1;
				}
			}
			sem_post(semMemoria);
//                } // fin if
		break;
	}
//	wait(NULL);

}


/* ----- monitor maxi ------ */
void ejecutarMonitor()
{

       char linea[30];
       char c_shmid[30];
       //char c_shmidMon[30];
       char c_shmidMon2[30];

       shmidMon2 = shmget(SHMKEY,sizeof(linea),0666|IPC_CREAT);
       buffer = (char *)shmat(shmidMon2,(char*)0,0);

       pid_t pidTemp = fork();

       if( pidTemp == 0 )  // proceso monitor
       {
    	   buffer[sizeof(buffer)]='\0';
           sprintf(buffer,"%d",getpid());  // almacena el pidMonitor en la shm
           sprintf(c_shmid,"%d",id_memo);  // almacena el la mememoria en la shm
           //sprintf(c_shmidMon,"%d",shmidMonitor);
           sprintf(c_shmidMon2,"%d",shmidMon2);
           //cout<<"inicio de ejecucion de Monitor"<<endl;
           if(execlp(PATH_MON,"MonitorTorneo",c_shmid,c_shmidMon2,NULL) == -1);
           	   	   cout<<"execlp fallido"<<endl;
       }

       sleep(2); // el hijo debe lanzar el monitor antes que el padre llame al thread
       pthread_cond_broadcast(&cond_monitor);
}


/* ------  monitor maxi ------ */
void * monitorizarMonitor(void *arg)
{
   pthread_cond_wait(&cond_monitor,&mutex_monitor);
  

      int pidMonitor;
      //char *buffer;
      //char linea[30];

      //shmidMonitor = shmget(SHMKEY,sizeof(linea),0666 | IPC_CREAT);

      //buffer = (char *)shmat(shmidMonitor,(char*)0,0);
      //buffer[sizeof(buffer)]='\0';

      //printf("MEMORIA A ELIMINAR: %d", shmidMonitor);

    while(1)
    {

      usleep(1000000*1);  // 1 seg

      pidMonitor = atoi(buffer);

       if( kill(pidMonitor,0) == -1 )
       {
         cout<<"EL MONITOR HA DEJADO DE EJECUTAR"<<endl;
         reEjecutarMonitor();
         //pthread_cond_wait(&cond_monitor,&mutex_monitor);
       }
      printf("Monitor del torneo %d \n",pidMonitor);
       cout<<"El monitor esta ejecutando"<<endl;

   } // fin while
}


void reEjecutarMonitor()
{

       pid_t pidTemp = fork();
       char c_shmid[30];
       char c_shmidMon2[30];

       if( pidTemp == 0 )  // proceso monitor
       {
    	   buffer[sizeof(buffer)]='\0';
           sprintf(buffer,"%d",getpid());  // almacena el pidMonitor en la shm
           sprintf(c_shmid,"%d",id_memo);  // almacena el la mememoria en la shm
           //sprintf(c_shmidMon,"%d",shmidMonitor);
           sprintf(c_shmidMon2,"%d",shmidMon2);
           //cout<<"inicio de ejecucion de Monitor"<<endl;
           if(execlp(PATH_MON,"MonitorTorneo",c_shmid,c_shmidMon2,NULL) == -1);
           	   	   cout<<"execlp fallido"<<endl;
       }

       sleep(2); // el hijo debe lanzar el monitor antes que el padre llame al thread
       //pthread_cond_broadcast(&cond_monitor);
}

int verificar_proceso_monitor(void)
{

     char procesoTorneo[100]="ps ax | grep MonitorTorneo | grep -v grep | cut -d' ' -f2";

         FILE *r_procesoTorneo = popen(procesoTorneo,"r");
         char pid_buffer[30] = "xxx";
         fscanf(r_procesoTorneo,"%100s",pid_buffer);
         pclose(r_procesoTorneo);

        if(strcmp(pid_buffer,"xxx") != 0)
           return 1;
        else
           return 0;
     

}
